//
//  RBMediaPlayerView.m
//  RBVideoPlayer
//
//  Created by Lan on 2017/8/4.
//  Copyright © 2017年 SummerTea. All rights reserved.
//

#import "RBMediaPlayerView.h"
#import "RBVideoControlsView.h"
#import "RBVideoFullScreenVC.h"
#import <MediaPlayer/MediaPlayer.h>
#import "RBVideoBrightnessView.h"
#import "RBVideoFastForwardView.h"

@interface RBMediaPlayerView ()

@property(nonatomic, strong) RBMediaPlayer *player;
@property(nonatomic, strong) UIView *bottomContentView;
@property(nonatomic, strong) UIView *topContentView;
@property(nonatomic, strong) RBVideoControlsView *videoControlsView;

@property(nonatomic, assign) CGFloat duration;
@property(nonatomic, assign) CGFloat timeoffset;

@property(nonatomic, strong) UISlider *volumeSlider;
@property(nonatomic, assign) CGFloat beginVolume;

@property(nonatomic, strong) RBVideoBrightnessView *brightnessView;
@property(nonatomic, assign) CGFloat beginBrightness;

@property(nonatomic, strong) RBVideoFastForwardView *fastForwardView;
@property(nonatomic, assign) CGFloat beginFastForward;

@property(nonatomic, assign) CGFloat rate;
@property(nonatomic, assign) BOOL locked;

//full screen
@property(nonatomic, strong) RBVideoFullScreenVC *vc;
@property(nonatomic, assign) UIDeviceOrientation orientation;

@end

@implementation RBMediaPlayerView

#pragma mark - System

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
        self.orientation = UIDeviceOrientationPortrait;
        
        self.backgroundColor = [UIColor blackColor];
        self.videoControlsView.hidden = NO;
        self.beginVolume = CGFLOAT_MIN;
        self.beginBrightness = CGFLOAT_MIN;
        self.beginFastForward = CGFLOAT_MIN;
        self.rate = 1;
        self.locked = NO;
        
        [self portraitSettings];
    }
    return self;
}

- (void)dealloc
{
    [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)layoutSubviews
{
    [super layoutSubviews];
    
    if (self.orientation == UIDeviceOrientationPortrait)
    {
        self.bottomContentView.frame = self.bounds;
    }
    self.topContentView.frame = self.bottomContentView.bounds;
    self.videoControlsView.frame = self.topContentView.bounds;
    [self.player setPictureFrame:self.bottomContentView.bounds];
}

#pragma mark - Private

- (NSString *)textFromSeconds: (float)seconds
{
    NSInteger count = (NSInteger)seconds;
    NSInteger hour = count / 3600;
    NSInteger minute = count % 3600 / 60;
    NSInteger second = count % 60;
    NSString *text;
    if (hour)
    {
        text = [NSString stringWithFormat:@"%02zd:%02zd:%02zd", hour, minute, second];
    }
    else
    {
        text = [NSString stringWithFormat:@"%02zd:%02zd", minute, second];
    }
    return text;
}

- (UIViewController *)controller
{
    UIResponder *res = self.nextResponder;
    while (![res isKindOfClass:[UIViewController class]] && ![res isKindOfClass:[UIWindow class]])
    {
        res = res.nextResponder;
    }
    if ([res isKindOfClass:[UIViewController class]])
    {
        return (UIViewController *)res;
    }
    else
    {
        return nil;
    }
}

- (void)pause
{
    if (self.player.status != RBMediaPlayerStatusUnavailable)
    {
        if (self.player.playing)
        {
            [self.player pause];
        }
    }
}

- (RBVideoFullScreenVC *)fullScreenVc
{
    __weak typeof(self) weakSelf = self;
    RBVideoFullScreenVC *vc = [RBVideoFullScreenVC new];
    vc.viewWillDisapperBlock = ^{
        [weakSelf pause];
        [weakSelf showWithOrientation:UIDeviceOrientationPortrait animated:NO];
    };
    return vc;
}

- (void)showWithOrientation: (UIDeviceOrientation) orientation animated: (BOOL)animated
{
    //没做动画
    
    if (orientation == UIDeviceOrientationUnknown)
    {
        return;
    }
    
    if (self.orientation == orientation)
    {
        return;
    }
    
    __weak typeof(self) weak_self = self;
    CGFloat animationDuration = 0.2;
    self.orientation = orientation;
    
    switch (orientation)
    {
        case UIDeviceOrientationPortrait:
        {
            [self portraitSettings];
            
            self.vc.viewWillDisapperBlock = nil;
            [self.vc dismissViewControllerAnimated:NO completion:nil];
            self.vc = nil;
            self.bottomContentView.frame = self.bounds;
            [self addSubview:self.bottomContentView];
        }
            break;
        case UIDeviceOrientationLandscapeRight:
        case UIDeviceOrientationLandscapeLeft:
        {
            /*
            CGFloat left = 0;
            CGFloat right = 0;
            CGFloat angle = 0;
            CGFloat width = MIN(UIScreen.mainScreen.bounds.size.width, UIScreen.mainScreen.bounds.size.height);
            CGFloat height = MAX(UIScreen.mainScreen.bounds.size.width, UIScreen.mainScreen.bounds.size.height);
            if (orientation == UIDeviceOrientationLandscapeRight)
            {
                left = [self theSafeEdge].top;
                right = [self theSafeEdge].bottom;
                angle = -M_PI/2;
            }
            else if(orientation == UIDeviceOrientationLandscapeLeft)
            {
                left = [self theSafeEdge].bottom;
                right = [self theSafeEdge].top;
                angle = M_PI/2;
            }
            if (left <= 20)
            {
                left = 0;
            }
            if (right <= 20)
            {
                right = 0;
            }
            height -= left;
            height -= right;
             */
             
            [self landscapeSettings];
            
            self.vc = [self fullScreenVc];
            self.vc.preferredInterfaceOrientation = [self preferredInterfaceOrientation];
            [self.vc showWithVC:[self controller] viewAppeared:^(UIView *containerView){
                [containerView addSubview:weak_self.bottomContentView];
                weak_self.bottomContentView.frame = containerView.bounds;
                [weak_self layoutSubviews];
            }];
        }
            break;
        default:
            break;
    }
}

- (void)seekToProgress: (CGFloat)progress
{
    if (self.player.status == RBMediaPlayerStatusUnavailable)
    {//用处不大
        return;
    }
    [self.videoControlsView.slider setPlayProgress:progress];
    [self.player seekToTime:self.player.duration*progress];
    self.videoControlsView.currentTimeLabel.text = [self textFromSeconds:progress * self.duration];
}

- (UIWindow *)keyWindow
{
    if (_keyWindow)
    {
        return _keyWindow;;
    }
    else
    {    
        return UIApplication.sharedApplication.keyWindow;
    }
}

- (UIInterfaceOrientation)preferredInterfaceOrientation
{
    if ([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeLeft || [UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeRight)
    {
        return (UIInterfaceOrientation)[UIDevice currentDevice].orientation;
    }
    else
    {
        return UIInterfaceOrientationLandscapeRight;
    }
}

- (UIEdgeInsets)theSafeEdge
{
    if (@available(iOS 11.0, *)){
        return UIApplication.sharedApplication.keyWindow.safeAreaInsets;
    };
    return UIEdgeInsetsZero;
}

#pragma mark - Setting(个性化设置)

- (void)portraitSettings
{
    self.videoControlsView.topBar.hidden = YES;
    self.videoControlsView.lockScreenBtn.hidden = YES;
}

- (void)landscapeSettings
{
    self.videoControlsView.topBar.hidden = NO;
    self.videoControlsView.lockScreenBtn.hidden = NO;
}

#pragma mark - Public

- (void)setURL: (NSURL *)url timeOffset: (float)timeoffset title: (NSString *)title playImmediately: (BOOL)playImmediately
{
    self.timeoffset = timeoffset;
    self.duration = 0;
    [self.player stop];
    [self.player setSources:@[url? url: [NSURL new]]];
    [self.player addPictureToLayer:self.bottomContentView.layer frame:self.bounds];
    [self.bottomContentView bringSubviewToFront:self.topContentView];
    self.videoControlsView.titleLabel.text = title;
    self.videoControlsView.currentTimeLabel.text = [self textFromSeconds:0];
    self.videoControlsView.durationLabel.text = [self textFromSeconds:0];
    self.videoControlsView.slider.playProgress = 0;
    self.videoControlsView.slider.cacheProgress = 0;
    if (playImmediately)
    {
        self.videoControlsView.tipView.text = @"视频加载中...";
        [self.player play];
        self.videoControlsView.playing = YES;
    }
    else
    {
        self.videoControlsView.tipView.text = @"";
        self.videoControlsView.playing = NO;
    }
}

#pragma mark - Event

- (void)backBtnTapped
{
    [self showWithOrientation:UIDeviceOrientationPortrait animated:YES];
}

- (void)rateBtnTapped
{
    if (self.forceWatch)
    {
        return;
    }
    CGFloat rate = self.rate;
    NSArray *rates = @[@(0.5), @(1), @(1.5), @(2)];
    NSInteger index = [rates indexOfObject:@(rate)] + 1;
    if (index >= rates.count)
    {
        index = 0;
    }
    NSNumber *number = rates[index];
    [self.videoControlsView.rateBtn setTitle:[NSString stringWithFormat:@"%@X", number] forState:UIControlStateNormal];
    self.rate = number.floatValue;
    if (self.player.status == RBMediaPlayerStatusPlaying)
    {
        self.player.rate = self.rate;
    }
}

- (void)playBtnTapped: (UIButton *)btn
{
    if (self.player.status == RBMediaPlayerStatusUnavailable)
    {
        [self.player play];
    }
    else
    {
        if (self.player.playing)
        {
            [self.player pause];
        }
        else
        {
            [self.player resume];
        }
    }
}

- (void)fullScreenBtnTapped: (UIButton *)btn
{
    if (self.orientation == UIDeviceOrientationPortrait)
    {
        [self.videoControlsView.fullScreenBtn setImage:[UIImage imageNamed:@"RBMediaPlayer.bundle/nonfullscreen"] forState:UIControlStateNormal];
        [self showWithOrientation:(UIDeviceOrientation)[self preferredInterfaceOrientation] animated:YES];
    }
    else
    {
        [self.videoControlsView.fullScreenBtn setImage:[UIImage imageNamed:@"RBMediaPlayer.bundle/fullscreen"] forState:UIControlStateNormal];
        [self showWithOrientation:UIDeviceOrientationPortrait animated:YES];
    }
}

#pragma mark - Setter

- (void)setDuration:(CGFloat)duration
{
    _duration = duration;
    self.videoControlsView.durationLabel.text = [self textFromSeconds:duration];
}

- (void)setForceWatch:(BOOL)forceWatch
{
    _forceWatch = forceWatch;
    self.videoControlsView.slider.userInteractionEnabled = !forceWatch;
}

#pragma mark - Getter

- (UISlider *)volumeSlider
{
    if (!_volumeSlider)
    {
        MPVolumeView *view = [MPVolumeView new];
        for (UIControl *subView in view.subviews) {
            if ([subView.superclass isSubclassOfClass:[UISlider class]]) {
                self.volumeSlider = (UISlider *)subView;
            }
        }
        if (!_volumeSlider)
        {
            self.volumeSlider = [UISlider new];
        }
    }
    return _volumeSlider;
}

- (RBMediaPlayer *)player
{
    if (!_player)
    {
        self.player = ({
            RBMediaPlayer *player = [RBMediaPlayer new];
            __weak typeof(self) weak_self = self;
            player.durationBlock = ^(CGFloat duration, CGFloat currentTime, NSURL *url){
                weak_self.duration = duration;
                if (weak_self.playTimeBlock)
                {
                    weak_self.playTimeBlock(currentTime);
                }
                if (!weak_self.videoControlsView.slider.dragging)
                {
                    weak_self.videoControlsView.currentTimeLabel.text = [weak_self textFromSeconds:currentTime];
                    weak_self.videoControlsView.slider.playProgress = isnan(currentTime/duration)? 0: currentTime/duration;
                }
            };
            player.statusBlock = ^(RBMediaPlayerStatus status, NSURL *url){
                switch (status) {
                    case RBMediaPlayerStatusReadyToPlay:
                    {
                        weak_self.videoControlsView.indicatorView.hidden = NO;
                        [weak_self.videoControlsView.indicatorView startAnimating];
                        weak_self.videoControlsView.tipView.text = nil;
                        weak_self.videoControlsView.playing = YES;
                        if (weak_self.timeoffset > 0)
                        {
                            [weak_self.player seekToTime:weak_self.timeoffset];
                        }
                    }
                        break;
                    case RBMediaPlayerStatusUnavailable:
                    {
                        weak_self.videoControlsView.indicatorView.hidden = YES;
                        [weak_self.videoControlsView.indicatorView stopAnimating];
                        weak_self.videoControlsView.tipView.text = @"无法播放";
                        weak_self.videoControlsView.playing = NO;
                    }
                        break;
                    case RBMediaPlayerStatusPlaying:
                    {
                        weak_self.videoControlsView.indicatorView.hidden = YES;
                        [weak_self.videoControlsView.indicatorView stopAnimating];
                        weak_self.videoControlsView.tipView.text = nil;
                        weak_self.videoControlsView.playing = YES;
                        if (weak_self.player.rate != weak_self.rate)
                        {
                            weak_self.player.rate = weak_self.rate;
                        }
                    }
                        break;
                    case RBMediaPlayerStatusBuffering:
                    {
                        weak_self.videoControlsView.indicatorView.hidden = NO;
                        [weak_self.videoControlsView.indicatorView startAnimating];
                        weak_self.videoControlsView.tipView.text = nil;
                        weak_self.videoControlsView.playing = YES;
                    }
                        break;
                    case RBMediaPlayerStatusPaused:
                    {
                        weak_self.videoControlsView.indicatorView.hidden = YES;
                        [weak_self.videoControlsView.indicatorView stopAnimating];
                        weak_self.videoControlsView.tipView.text = nil;
                        weak_self.videoControlsView.playing = NO;
                    }
                        break;
                    case RBMediaPlayerStatusPlayToEnd:
                    {
                        weak_self.videoControlsView.indicatorView.hidden = YES;
                        [weak_self.videoControlsView.indicatorView stopAnimating];
                        weak_self.videoControlsView.tipView.text = nil;
                        weak_self.videoControlsView.playing = NO;
                        weak_self.videoControlsView.slider.playProgress = 0;
                        weak_self.videoControlsView.slider.cacheProgress = 0;
                        [weak_self.player seekToTime:0];
                        if (weak_self.watchEndBlock)
                        {
                            weak_self.watchEndBlock();
                        }
                    }
                        break;
                    default:
                        break;
                }
            };
            player.cacheBlock = ^(CGFloat duration, CGFloat cacheTime, NSURL *url){
                weak_self.duration = duration;
                weak_self.videoControlsView.slider.cacheProgress = isnan(cacheTime/duration)? 0: cacheTime/duration;
            };
            player;
        });
    }
    return _player;
}

- (RBVideoFastForwardView *)fastForwardView
{
    if (!_fastForwardView)
    {
        self.fastForwardView = ({
            RBVideoFastForwardView *view = [RBVideoFastForwardView new];
            [self.bottomContentView addSubview:view];
            view;
        });
    }
    return _fastForwardView;
}

- (UIView *)bottomContentView
{
    if (!_bottomContentView)
    {
        self.bottomContentView = ({
            UIView *view = [UIView new];
            view.backgroundColor = [UIColor blackColor];
            view.frame = self.bounds;
            [self addSubview:view];
            view;
        });
    }
    return _bottomContentView;
}

- (UIView *)topContentView
{
    if (!_topContentView)
    {
        self.topContentView = ({
            UIView *view = [UIView new];
            view.backgroundColor = [UIColor clearColor];
            [self.bottomContentView addSubview:view];
            view;
        });
    }
    return _topContentView;
}

- (RBVideoControlsView *)videoControlsView
{
    if (!_videoControlsView)
    {
        self.videoControlsView = ({
            RBVideoControlsView *view = [RBVideoControlsView new];
            [view.backBtn addTarget:self action:@selector(backBtnTapped) forControlEvents:UIControlEventTouchUpInside];
            [view.rateBtn addTarget:self action:@selector(rateBtnTapped) forControlEvents:UIControlEventTouchUpInside];
            [view.playBtn addTarget:self action:@selector(playBtnTapped:) forControlEvents:UIControlEventTouchUpInside];
            [view.fullScreenBtn addTarget:self action:@selector(fullScreenBtnTapped:) forControlEvents:UIControlEventTouchUpInside];
            __weak typeof(self) weak_self = self;
            view.doubleTapBlock = ^{
                if (weak_self.player.playing)
                {
                    [weak_self.player pause];
                }
                else
                {
                    [weak_self.player resume];
                }
            };
            view.swipeBlock = ^(RBVideoSwipeDirection direction, CGFloat progress, BOOL end) {
                switch (direction) {
                    case RBVideoSwipeDirectionHor:
                    {
                        if (weak_self.forceWatch)
                        {
                            return;
                        }
                        if (weak_self.player.duration > 1)
                        {
                            if (end)
                            {
                                weak_self.beginFastForward = CGFLOAT_MIN;
                                [weak_self.fastForwardView hide];
                            }
                            else
                            {
                                if (weak_self.beginFastForward == CGFLOAT_MIN)
                                {
                                    weak_self.beginFastForward = weak_self.player.currentTime;
                                }
                                [weak_self.fastForwardView showWithBeginTime:weak_self.beginFastForward totalTime:weak_self.player.duration progress:progress endBlock:^(NSInteger time) {
                                    [weak_self seekToProgress:time*1.0/weak_self.player.duration];
                                }];
                            }
                        }
                    }
                        break;
                    case RBVideoSwipeDirectionLeftVer:
                    {
                        if (end)
                        {
                            weak_self.beginBrightness = CGFLOAT_MIN;
                            [weak_self.brightnessView hide];
                            weak_self.brightnessView = nil;
                        }
                        else
                        {
                            if (weak_self.beginBrightness == CGFLOAT_MIN)
                            {
                                weak_self.beginBrightness = [UIScreen mainScreen].brightness;
                                weak_self.brightnessView = [RBVideoBrightnessView new];
                                [weak_self.brightnessView show];
                                weak_self.brightnessView.transform = weak_self.bottomContentView.transform;
                            }
                            CGFloat value = weak_self.beginBrightness;
                            value += progress*2.0;
                            value = MAX(0, value);
                            value = MIN(1, value);
                            [UIScreen mainScreen].brightness = value;
                            [weak_self.brightnessView setBrightness:value];
                        }
                    }
                        break;
                    case RBVideoSwipeDirectionRightVer:
                    {
                        if (end)
                        {
                            weak_self.beginVolume = CGFLOAT_MIN;
                        }
                        else
                        {
                            if (weak_self.beginVolume == CGFLOAT_MIN)
                            {
                                weak_self.beginVolume = weak_self.volumeSlider.value;
                            }
                            CGFloat value = weak_self.beginVolume;
                            value += progress*2.0;
                            value = MAX(0, value);
                            value = MIN(1, value);
                            weak_self.volumeSlider.value = value;
                        }
                    }
                        break;
                    default:
                        break;
                }
            };
            view.slider.railTapBlock = ^(CGFloat progress) {
                [weak_self seekToProgress:progress];
            };
            view.slider.dragEndBlock = ^(CGFloat playProgress){
                [weak_self.player seekToTime:playProgress * weak_self.duration];
            };
            view.slider.dragChangedBlock = ^(CGFloat playProgress){
                weak_self.videoControlsView.currentTimeLabel.text = [weak_self textFromSeconds:playProgress * weak_self.duration];
            };
            [self.topContentView addSubview:view];
            view;
        });
    }
    return _videoControlsView;
}

@end
